<template>
  <div class="test-view">
    <SideNav />
    <div class="main-content">
      <h1>组件测试区</h1>
      
      <!-- 消息提示测试区 -->
      <div class="test-section">
        <h2>消息提示测试</h2>
        <div class="test-buttons">
          <button v-for="btn in messageButtons" 
                  :key="btn.type"
                  :class="['test-btn', btn.type]"
                  @click="btn.action">
            <i :class="btn.icon"></i>
            {{ btn.text }}
          </button>
        </div>
      </div>

      <!-- 消息提示组件 -->
      <MessagePopup
        :visible="showMessage"
        :type="messageType"
        :title="messageTitle"
        :message="messageText"
        :duration="2000"
        @update:visible="showMessage = $event"
        @close="handleClose"
      />
      
      <!-- 确认框组件 -->
      <MessagePopup
        :visible="showConfirm"
        type="warning"
        title="确认操作"
        message="这是一个需要确认的重要操作，是否继续？"
        :showConfirm="true"
        :showCancel="true"
        confirmText="确认"
        cancelText="取消"
        :duration="0"
        @update:visible="showConfirm = $event"
        @confirm="handleConfirm"
        @cancel="handleCancel"
      />

      <!-- 富文本编辑器测试区 -->
      <div class="test-section editor-section">
        <div class="section-header">
          <h2>富文本编辑器测试</h2>
          <div class="editor-actions">
            <button class="test-btn info" @click="clearEditor">
              <i class="fas fa-eraser"></i>
              清空内容
            </button>
          </div>
        </div>
        
        <div class="editor-container">
          <RichTextEditor 
            v-model="editorContent"
            class="custom-editor" 
            @upload-image="handleImageUpload"
            @delete-image="handleImageDelete"
          />
        </div>

        <div class="editor-preview-container" v-if="editorContent">
          <div class="preview-header">
            <h3>
              <i class="fas fa-code"></i>
              HTML 结构
            </h3>
            <span class="content-length">字符数：{{ contentLength }}</span>
          </div>
          <div class="preview-content html-mode">
            <pre><code>{{ editorContent }}</code></pre>
          </div>
        </div>
      </div>

      <!-- AI对话测试区 -->
      <div class="test-section">
        <h2>AI对话测试</h2>
        <div class="chat-container">
          <div class="chat-messages" ref="messageContainer">
            <div v-for="(msg, index) in chatMessages" 
                 :key="index" 
                 :class="['message', msg.role]">
              <div v-if="msg.isHtml" v-html="msg.content"></div>
              <div v-else>{{ msg.content }}</div>
            </div>
            <div v-if="isLoading" class="message ai loading">
              <div class="loading-text">
                正在询问AI，请稍等
                <span class="dots"><span>.</span><span>.</span><span>.</span></span>
              </div>
            </div>
          </div>
          <div class="chat-input">
            <textarea 
              v-model="userInput"
              placeholder="请输入您的问题..."
              @keydown.enter.prevent="userInput += '\n'"
              :rows="1"
              :style="{ height: 'auto', minHeight: '40px' }"
              @input="adjustHeight"
            ></textarea>
            <button 
              class="test-btn info" 
              @click="sendMessage"
              :disabled="isLoading">
              <i class="fas fa-paper-plane"></i>
              发送
            </button>
          </div>
        </div>
      </div>

      <!-- 代码测试区 -->
      <div class="test-section">
        <h2>代码测试</h2>
        <div class="code-test-container">
          <!-- 语言选择 -->
          <div class="language-select">
            <label>编程语言：</label>
            <select v-model="selectedLanguage" class="language-dropdown">
              <option v-for="lang in languages" 
                      :key="lang.id" 
                      :value="lang.id">
                {{ lang.name }}
              </option>
            </select>
          </div>

          <!-- 代码输入 -->
          <div class="code-input-section">
            <label>源代码：</label>
            <textarea 
              v-model="sourceCode"
              class="code-textarea"
              placeholder="请输入您的代码..."
              spellcheck="false"
            ></textarea>
          </div>

          <!-- 测试用例设置 -->
          <div class="test-cases-section">
            <div class="test-cases-header">
              <h3>测试设置</h3>
              <div class="test-cases-toggle">
                <label class="switch">
                  <input type="checkbox" v-model="hasTestCases">
                  <span class="slider round"></span>
                </label>
                <span class="toggle-label">使用测试用例</span>
              </div>
            </div>

            <!-- 无测试用例时的输出设置 -->
            <div v-if="!hasTestCases" class="single-output-section">
              <label>预期输出：</label>
              <textarea 
                v-model="singleOutput"
                class="output-textarea"
                placeholder="请输入预期输出..."
              ></textarea>
            </div>

            <!-- 有测试用例时的输入输出设置 -->
            <div v-else class="test-cases-container">
              <div class="test-cases-controls">
                <button 
                  class="test-btn info small"
                  @click="addTestCase"
                  title="添加测试用例">
                  <i class="fas fa-plus"></i>
                  添加测试用例
                </button>
              </div>
              
              <div 
                v-for="(testCase, index) in testCases" 
                :key="index"
                class="test-case-item"
              >
                <div class="test-case-header">
                  <h4>测试用例 #{{index + 1}}</h4>
                  <button 
                    v-if="testCases.length > 1"
                    class="delete-btn"
                    @click="removeTestCase(index)"
                    title="删除此测试用例">
                    <i class="fas fa-times"></i>
                  </button>
                </div>
                
                <div class="test-case-content">
                  <div class="input-group">
                    <label>输入：</label>
                    <textarea 
                      v-model="testCase.input"
                      class="case-textarea"
                      placeholder="请输入测试数据..."
                    ></textarea>
                  </div>
                  <div class="input-group">
                    <label>预期输出：</label>
                    <textarea 
                      v-model="testCase.expectedOutput"
                      class="case-textarea"
                      placeholder="请输入预期输出..."
                    ></textarea>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- 在测试用例设置后，提交按钮前添加 -->
          <div class="execution-limits-section">
            <div class="limits-header">
              <h3>执行约束</h3>
              <div class="limits-toggle">
                <label class="switch">
                  <input type="checkbox" v-model="hasExecutionLimits">
                  <span class="slider round"></span>
                </label>
                <span class="toggle-label">启用限制</span>
              </div>
            </div>

            <div v-if="hasExecutionLimits" class="limits-content">
              <div class="limit-item">
                <label>最大执行时间</label>
                <div class="limit-input-group">
                  <input 
                    type="number" 
                    v-model.number="executionLimits.timeLimit"
                    :min="executionLimits.timeUnit === 's' ? 0.1 : 100"
                    :max="executionLimits.timeUnit === 's' ? 30 : 30000"
                    :step="executionLimits.timeUnit === 's' ? 0.1 : 100"
                    class="limit-input"
                  >
                  <select 
                    v-model="executionLimits.timeUnit"
                    class="unit-select"
                    @change="handleTimeUnitChange"
                  >
                    <option value="s">秒</option>
                    <option value="ms">毫秒</option>
                  </select>
                </div>
              </div>
              <div class="limit-item">
                <label>最大内存使用</label>
                <div class="limit-input-container">
                  <div class="limit-input-group">
                    <input 
                      type="number" 
                      v-model.number="executionLimits.memoryLimit"
                      :class="['limit-input', {'invalid': !memoryInputStatus.isValid}]"
                      @input="validateMemoryLimit"
                    >
                    <select 
                      v-model="executionLimits.memoryUnit"
                      class="unit-select"
                      @change="handleMemoryUnitChange"
                    >
                      <option value="MB">MB</option>
                      <option value="KB">KB</option>
                    </select>
                  </div>
                  <div v-if="!memoryInputStatus.isValid" class="input-error-message">
                    {{ memoryInputStatus.message }}
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- 修改提交按钮部分，添加加载动画 -->
          <div class="submit-section">
            <button 
              class="test-btn info"
              @click="submitCode"
              :disabled="isSubmitting">
              <template v-if="!isSubmitting">
                <i class="fas fa-play"></i>
                运行测试
              </template>
              <template v-else>
                <div class="loading-container">
                  <div class="loading-stage">
                    <div class="stage-indicator">
                      <div 
                        v-for="(stage, index) in loadingStages" 
                        :key="index"
                        class="stage-dot"
                        :class="{
                          'active': index === currentStage,
                          'completed': index < currentStage
                        }"
                      ></div>
                    </div>
                    <span class="stage-text">{{ loadingStages[currentStage] }}</span>
                  </div>
                </div>
              </template>
            </button>
          </div>

          <!-- 测试结果 -->
          <div v-if="testResult" class="test-result" :class="[testResult.status, {'limit-exceeded': testResult.limitExceeded}]">
            <div class="result-header">
              <div class="status-info">
                <span class="result-status">
                  <i :class="getStatusIcon(testResult.status)"></i>
                  {{ testResult.statusText }}
                </span>
              </div>
              <div class="performance-info">
                <span class="result-time" :class="{'exceeded': testResult.exceededType === 'time'}" v-if="testResult.time">
                  <i class="fas fa-clock"></i>
                  执行时间: {{ testResult.time }}
                </span>
                <span class="result-memory" :class="{'exceeded': testResult.exceededType === 'memory'}" v-if="testResult.memory">
                  <i class="fas fa-memory"></i>
                  内存占用: {{ testResult.memory }}
                </span>
              </div>
            </div>
            
            <!-- 标准输出 -->
            <div v-if="testResult.output" class="result-section">
              <div class="section-header">
                <i class="fas fa-terminal"></i>
                程序输出
              </div>
              <div class="result-details">
                <pre><code>{{ testResult.output }}</code></pre>
              </div>
            </div>

            <!-- 编译错误输出 -->
            <div v-if="testResult.compileOutput" class="result-section error">
              <div class="section-header">
                <i class="fas fa-exclamation-triangle"></i>
                编译错误
              </div>
              <div class="result-details">
                <pre><code>{{ testResult.compileOutput }}</code></pre>
              </div>
            </div>

            <!-- 运行时错误输出 -->
            <div v-if="testResult.stderr" class="result-section error">
              <div class="section-header">
                <i class="fas fa-bug"></i>
                运行时错误
              </div>
              <div class="result-details">
                <pre><code>{{ testResult.stderr }}</code></pre>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 添加全屏加载蒙版 -->
    <div v-if="isSubmitting" class="loading-overlay">
      <div class="loading-content">
        <div class="loading-stage">
          <div class="stage-indicator">
            <div 
              v-for="(stage, index) in loadingStages" 
              :key="index"
              class="stage-dot"
              :class="{
                'active': index === currentStage,
                'completed': index < currentStage
              }"
            ></div>
          </div>
          <span class="stage-text">{{ loadingStages[currentStage] }}</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import SideNav from '@/components/SideNav.vue'
import MessagePopup from '@/components/MessagePopup.vue'
import { marked } from 'marked';
import hljs from 'highlight.js';
import 'highlight.js/styles/vs2015.css';
import { baseURL } from '@/utils/api';
import RichTextEditor from '@/components/RichTextEditor.vue'

// 配置 marked
marked.setOptions({
  highlight: function(code, lang) {
    if (lang && hljs.getLanguage(lang)) {
      return hljs.highlight(code, { language: lang }).value;
    }
    return hljs.highlightAuto(code).value;
  },
  breaks: true
});

export default {
  name: 'TestView',
  components: {
    SideNav,
    MessagePopup,
    RichTextEditor,
  },
  data() {
    return {
      showMessage: false,
      showConfirm: false,
      messageType: 'success',
      messageTitle: '',
      messageText: '',
      userInput: '',
      chatMessages: [],
      isLoading: false,
      editorContent: '',
      uploadedImages: [],
      messageId: 0,
      languages: [],
      selectedLanguage: null,
      sourceCode: '',
      testInput: '',
      expectedOutput: '',
      isSubmitting: false,
      testResult: null,
      hasTestCases: false,
      testCases: [{ input: '', expectedOutput: '' }],
      singleOutput: '',
      hasExecutionLimits: false,
      executionLimits: {
        timeLimit: 2.0,
        timeUnit: 's',
        memoryLimit: 128,
        memoryUnit: 'MB'
      },
      memoryInputStatus: {
        isValid: true,
        message: ''
      },
      loadingStages: ['编译代码', '执行程序', '处理结果'],
      currentStage: 0,
    }
  },
  computed: {
    messageButtons() {
      return [
        {
          type: 'success',
          icon: 'fas fa-check-circle',
          text: '成功提示',
          action: () => this.showMessageWithType('success', '成功', '操作已成功完成！')
        },
        {
          type: 'error',
          icon: 'fas fa-times-circle',
          text: '错误提示',
          action: () => this.showMessageWithType('error', '错误', '操作失败，请重试！')
        },
        {
          type: 'warning',
          icon: 'fas fa-exclamation-circle',
          text: '警告提示',
          action: () => this.showMessageWithType('warning', '警告', '请注意，这是一个警告消息！')
        },
        {
          type: 'info',
          icon: 'fas fa-info-circle',
          text: '信息提示',
          action: () => this.showMessageWithType('info', '提示', '这是一条普通的信息提示！')
        },
        {
          type: 'confirm',
          icon: 'fas fa-question-circle',
          text: '确认框',
          action: () => this.showConfirmMessage()
        }
      ]
    },
    contentLength() {
      return this.editorContent.length;
    }
  },
  mounted() {
    window.addEventListener('beforeunload', this.handleBeforeUnload);
    this.fetchLanguages();
  },
  beforeDestroy() {
    window.removeEventListener('beforeunload', this.handleBeforeUnload);
  },
  methods: {
    showMessageWithType(type, title, text) {
      this.messageType = type;
      this.messageTitle = title;
      this.messageText = text;
      this.showMessage = true;
    },
    showConfirmMessage() {
      this.showConfirm = true;
    },
    handleConfirm() {
      this.showMessageWithType('success', '确认成功', '您已确认此操作！');
      this.showConfirm = false;
    },
    handleCancel() {
      this.showMessageWithType('info', '已取消', '您已取消此操作！');
      this.showConfirm = false;
    },
    handleClose() {
      console.log('消息已关闭');
    },
    async sendMessage() {
      if (!this.userInput.trim() || this.isLoading) return;
      
      const question = this.userInput.trim();
      this.chatMessages.push({
        id: this.messageId++,
        role: 'user',
        content: question
      });
      
      this.userInput = '';
      this.isLoading = true;

      this.$nextTick(() => {
        this.scrollToBottom();
      });

      try {
        const response = await fetch(baseURL+`/ai-service/AI/streamDeepSeek?QuestionContent=${encodeURIComponent(question)}`);
        const aiResponse = await response.text();
        
        this.chatMessages.push({
          id: this.messageId++,
          role: 'ai',
          content: marked(aiResponse),
          isHtml: true
        });

        this.$nextTick(() => {
          this.scrollToBottom();
        });

      } catch (error) {
        console.error('Error:', error);
        this.showMessageWithType('error', '错误', '发送消息失败，请重试！');
      } finally {
        this.isLoading = false;
      }
    },
    adjustHeight(e) {
      const textarea = e.target;
      textarea.style.height = 'auto';
      textarea.style.height = `${textarea.scrollHeight}px`;
    },
    clearEditor() {
      this.editorContent = ''
      this.uploadedImages = []
    },
    scrollToBottom() {
      const container = this.$refs.messageContainer;
      container.scrollTop = container.scrollHeight;
    },
    async handleImageUpload(file) {
      try {
        const formData = new FormData();
        formData.append('image', file);
        
        const response = await fetch(`${baseURL}/upload-image`, {
          method: 'POST',
          body: formData
        });
        
        const result = await response.json();
        if (result.success) {
          this.editorContent += `<img src="${result.url}" alt="上传图片" />`;
          
          this.uploadedImages.push({
            url: result.url,
            id: result.id
          });
        } else {
          this.showMessageWithType('error', '上传失败', '图片上传失败，请重试！');
        }
      } catch (error) {
        console.error('图片上传错误:', error);
        this.showMessageWithType('error', '错误', '上传图片时发生错误，请重试！');
      }
    },
    async handleImageDelete(imageUrl) {
      try {
        const image = this.uploadedImages.find(img => img.url === imageUrl);
        if (image) {
          const response = await fetch(`${baseURL}/delete-image/${image.id}`, {
            method: 'DELETE'
          });
          
          const result = await response.json();
          if (result.success) {
            this.uploadedImages = this.uploadedImages.filter(img => img.id !== image.id);
            this.editorContent = this.editorContent.replace(`<img src="${image.url}" alt="上传图片" />`, '');
            this.showMessageWithType('success', '删除成功', '图片已成功删除！');
          } else {
            this.showMessageWithType('error', '删除失败', '图片删除失败，请重试！');
          }
        }
      } catch (error) {
        console.error('图片删除错误:', error);
        this.showMessageWithType('error', '错误', '删除图片时发生错误，请重试！');
      }
    },
    handleBeforeUnload(event) {
      if (this.uploadedImages.length > 0) {
        this.uploadedImages.forEach(image => {
          const xhr = new XMLHttpRequest();
          xhr.open('DELETE', `${baseURL}/delete-image/${image.id}`, false);
          xhr.send(null);
        });
      }
    },
    async fetchLanguages() {
      try {
        const response = await fetch('http://39.106.42.243:2358/languages')
        const data = await response.json()
        this.languages = data
        if (data.length > 0) {
          this.selectedLanguage = data[0].id
        }
      } catch (error) {
        console.error('获取语言列表失败:', error)
        this.showMessageWithType('error', '错误', '获取支持的编程语言失败')
      }
    },
    async submitCode() {
      // 提交前验证
      this.validateMemoryLimit();
      if (!this.memoryInputStatus.isValid) {
        this.showMessageWithType('warning', '警告', this.memoryInputStatus.message);
        return;
      }

      if (!this.sourceCode.trim()) {
        this.showMessageWithType('warning', '警告', '请输入代码');
        return;
      }

      this.isSubmitting = true;
      this.testResult = null;
      this.currentStage = 0;

      try {
        let stdin = '';
        let expectedOutput = '';

        if (this.hasTestCases) {
          stdin = `${this.testCases.length}\n${this.testCases.map(tc => tc.input).join('\n')}`;
          expectedOutput = this.testCases.map(tc => tc.expectedOutput).join('\n');
        } else {
          stdin = '';
          expectedOutput = this.singleOutput;
        }

        // 准备提交数据
        const submission = {
          source_code: this.sourceCode,
          language_id: parseInt(this.selectedLanguage),
          stdin: stdin || null, // 如果为空字符串则设为 null
          expected_output: expectedOutput || null
        };

        // 添加执行限制
        if (this.hasExecutionLimits) {
          const timeLimit = this.executionLimits.timeUnit === 'ms' ? 
            this.executionLimits.timeLimit / 1000 : 
            this.executionLimits.timeLimit;
          
          const memoryLimit = this.convertMemoryValue(
            this.executionLimits.memoryLimit,
            this.executionLimits.memoryUnit,
            'KB'
          );

          // 验证限制值的合法性
          if (timeLimit > 0 && timeLimit <= 30) {
            submission.cpu_time_limit = timeLimit;
          }
          
          // 添加内存限制的最小值检查
          const MIN_MEMORY_KB = 2048; // 最小 2MB
          if (memoryLimit < MIN_MEMORY_KB) {
            throw new Error(`内存限制不能小于 2MB (${MIN_MEMORY_KB}KB)`);
          }
          
          submission.memory_limit = memoryLimit;
        }

        this.currentStage = 0;
        const submitResponse = await fetch('http://39.106.42.243:2358/submissions?base64_encoded=false&wait=false', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Accept': 'application/json'
          },
          body: JSON.stringify(submission)
        });

        if (!submitResponse.ok) {
          const errorData = await submitResponse.json().catch(() => null);
          throw new Error(
            errorData?.message || 
            `提交失败 (${submitResponse.status}): ${submitResponse.statusText}`
          );
        }

        const submitResult = await submitResponse.json();
        const token = submitResult.token;

        if (!token) {
          throw new Error('没有收到有效的token');
        }

        this.currentStage = 1;
        let result = null;
        let attempts = 0;
        const maxAttempts = 10;

        while (attempts < maxAttempts) {
          await new Promise(resolve => setTimeout(resolve, 1000));

          const resultResponse = await fetch(`http://39.106.42.243:2358/submissions/${token}?base64_encoded=false`, {
            headers: {
              'Accept': 'application/json'
            }
          });

          if (!resultResponse.ok) {
            throw new Error(`获取结果失败: ${resultResponse.status}`);
          }

          result = await resultResponse.json();
          console.log('获取的结果:', result); // 添加日志输出

          if (result.status.id >= 3) { // 状态ID >= 3 表示已完成
            break;
          }

          attempts++;
        }

        if (!result) {
          throw new Error('获取结果超时');
        }

        // 检查是否是内存超限导致的错误
        const isMemoryExceeded = 
          (result.message && result.message.includes('error status 137')) || 
          (result.stderr && result.stderr.includes('Killed'));

        // 检查是否超出用户设置的限制
        const timeExceeded = this.hasExecutionLimits && 
          parseFloat(result.time) > this.executionLimits.timeLimit;
        const memoryExceeded = this.hasExecutionLimits && 
          (this.executionLimits.memoryUnit === 'MB' ? 
            result.memory / 1024 > this.executionLimits.memoryLimit :
            result.memory > this.executionLimits.memoryLimit);

        if (isMemoryExceeded || timeExceeded || memoryExceeded) {
          this.testResult = {
            status: 'error',
            statusText: isMemoryExceeded ? '内存超限 (系统限制)' :
              timeExceeded ? `执行超时 (限制: ${this.executionLimits.timeLimit}s)` : 
              `内存超限 (限制: ${this.executionLimits.memoryLimit}${this.executionLimits.memoryUnit})`,
            time: this.formatTime(result.time),
            memory: this.formatMemory(result.memory),
            output: isMemoryExceeded ? 
              '程序因内存使用过多被系统终止' :
              '程序因超出资源限制被终止',
            limitExceeded: true,
            exceededType: timeExceeded ? 'time' : 'memory',
            details: isMemoryExceeded ? 
              '程序使用的内存超出系统限制，被强制终止。请尝试优化程序的内存使用。' : 
              undefined
          };
          return;
        }

        // 处理其他类型的错误
        switch (result.status.id) {
          case 3: // Accepted
            this.testResult = {
              status: 'success',
              statusText: '执行成功',
              time: this.formatTime(result.time),
              memory: this.formatMemory(result.memory),
              output: result.stdout || '程序没有输出'
            };
            break;
          case 6: // Compilation Error
            this.testResult = {
              status: 'error',
              statusText: '编译错误',
              time: '-',
              memory: '-',
              output: '编译失败，请检查代码语法',
              compileOutput: result.compile_output
            };
            break;
          case 5: // Time Limit Exceeded (系统限制)
            this.testResult = {
              status: 'error',
              statusText: '执行超时 (系统限制)',
              time: this.formatTime(result.time),
              memory: this.formatMemory(result.memory),
              output: '程序执行时间超出系统限制'
            };
            break;
          default:
            // 其他运行时错误
            this.testResult = {
              status: 'error',
              statusText: this.getStatusText(result.status.id),
              time: this.formatTime(result.time),
              memory: this.formatMemory(result.memory),
              output: result.stdout || '程序执行出错',
              stderr: result.stderr,
              details: this.getErrorDetails(result)
            };
        }

      } catch (error) {
        console.error('提交代码失败:', error);
        this.testResult = {
          status: 'error',
          statusText: '提交失败',
          output: `错误信息: ${error.message}`,
          time: '-',
          memory: '-'
        };
        // 如果是内存限制错误，显示更友好的提示
        if (error.message.includes('内存限制')) {
          this.showMessageWithType('warning', '警告', error.message);
        } else {
          this.showMessageWithType('error', '错误', '提交代码失败，请检查服务是否正常运行');
        }
      } finally {
        this.isSubmitting = false;
        this.currentStage = -1;
      }
    },
    getStatusClass(statusId) {
      const statusMap = {
        1: 'info',    // In Queue
        2: 'info',    // Processing
        3: 'success', // Accepted
        4: 'error',   // Wrong Answer
        5: 'error',   // Time Limit Exceeded
        6: 'error',   // Compilation Error
        7: 'error',   // Runtime Error (SIGSEGV)
        8: 'error',   // Runtime Error (SIGXFSZ)
        9: 'error',   // Runtime Error (SIGFPE)
        10: 'error',  // Runtime Error (SIGABRT)
        11: 'error',  // Runtime Error (NZEC)
        12: 'error',  // Runtime Error (Other)
        13: 'error',  // Internal Error
        14: 'warning' // Exec Format Error
      }
      return statusMap[statusId] || 'info'
    },
    getStatusText(statusId) {
      const statusMap = {
        1: '排队中',
        2: '执行中',
        3: '执行成功',
        4: '执行失败：结果错误',
        5: '执行超时',
        6: '编译错误',
        7: '段错误 (SIGSEGV)',
        8: '文件大小超限 (SIGXFSZ)',
        9: '浮点错误 (SIGFPE)',
        10: '程序异常终止 (SIGABRT)',
        11: '程序非正常退出 (NZEC)',
        12: '运行时错误',
        13: '系统内部错误',
        14: '执行格式错误'
      }
      return statusMap[statusId] || '未知状态'
    },
    formatMemory(memory, fixedDigits = 2) {
      if (!memory) return '0 KB';
      if (memory < 1024) return `${memory.toFixed(fixedDigits)} KB`;
      return `${(memory / 1024).toFixed(fixedDigits)} MB`;
    },
    formatTime(time) {
      return `${parseFloat(time).toFixed(3)}s`;
    },
    convertMemoryValue(value, fromUnit, toUnit) {
      if (fromUnit === toUnit) return value;
      if (fromUnit === 'MB' && toUnit === 'KB') return value * 1024;
      if (fromUnit === 'KB' && toUnit === 'MB') return value / 1024;
      return value;
    },
    handleMemoryUnitChange() {
      const oldValue = this.executionLimits.memoryLimit;
      const oldUnit = this.executionLimits.memoryUnit === 'MB' ? 'KB' : 'MB';
      const newUnit = this.executionLimits.memoryUnit;
      this.executionLimits.memoryLimit = this.convertMemoryValue(oldValue, oldUnit, newUnit);
      this.validateMemoryLimit();
    },
    handleTimeUnitChange() {
      const oldValue = this.executionLimits.timeLimit;
      const oldUnit = this.executionLimits.timeUnit === 's' ? 'ms' : 's';
      const newUnit = this.executionLimits.timeUnit;
      
      if (oldUnit === 'ms' && newUnit === 's') {
        this.executionLimits.timeLimit = oldValue / 1000;
      } else if (oldUnit === 's' && newUnit === 'ms') {
        this.executionLimits.timeLimit = oldValue * 1000;
      }
    },
    addTestCase() {
      this.testCases.push({ input: '', expectedOutput: '' });
    },
    removeTestCase(index) {
      this.testCases.splice(index, 1);
    },
    getStatusIcon(status) {
      const iconMap = {
        'success': 'fas fa-check-circle',
        'error': 'fas fa-times-circle',
        'warning': 'fas fa-exclamation-circle',
        'info': 'fas fa-info-circle'
      }
      return iconMap[status] || 'fas fa-question-circle';
    },
    getErrorDetails(result) {
      if (result.status.id === 11 && result.message?.includes('error status 137')) {
        return '程序因内存使用过多被系统终止。请检查是否存在内存泄漏或过度内存使用的问题。';
      }
      
      const errorMap = {
        7: '程序发生段错误。可能的原因：访问无效的内存地址、数组越界等。',
        8: '程序生成的文件过大。请检查是否有过量的输出操作。',
        9: '程序发生浮点数计算错误。请检查除零、溢出等数学运算问题。',
        10: '程序异常终止。请检查是否有未处理的异常情况。',
        11: '程序非正常退出。请检查程序的退出逻辑。',
        12: '程序发生未知运行时错误。请检查代码逻辑。'
      };
      
      return errorMap[result.status.id];
    },
    validateMemoryLimit() {
      const minMemory = this.executionLimits.memoryUnit === 'MB' ? 2 : 2048;
      const maxMemory = this.executionLimits.memoryUnit === 'MB' ? 512 : 524288;
      const currentValue = this.executionLimits.memoryLimit;

      if (currentValue < minMemory) {
        this.memoryInputStatus = {
          isValid: false,
          message: `内存不能小于 ${this.executionLimits.memoryUnit === 'MB' ? '2MB' : '2048KB'}`
        };
      } else if (currentValue > maxMemory) {
        this.memoryInputStatus = {
          isValid: false,
          message: `内存不能大于 ${this.executionLimits.memoryUnit === 'MB' ? '512MB' : '524288KB'}`
        };
      } else {
        this.memoryInputStatus = {
          isValid: true,
          message: ''
        };
      }
    }
  }
}
</script>

<style scoped>
.test-view {
  min-height: 100vh;
  background: #f0f7ff;
}

.main-content {
  margin-left: 60px;
  padding: 20px;
}

h1 {
  color: #2c3e50;
  margin-bottom: 30px;
}

.test-section {
  background: white;
  border-radius: 10px;
  padding: 20px;
  margin-bottom: 20px;
  box-shadow: 0 2px 12px rgba(164, 208, 246, 0.15);
}

h2 {
  color: #2c3e50;
  margin-bottom: 20px;
  font-size: 18px;
}

.test-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.test-btn {
  padding: 10px 20px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 8px;
  transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.test-btn:hover {
  transform: scale(1.05);
}

.test-btn.success {
  background: #42b983;
  color: white;
}

.test-btn.error {
  background: #f56c6c;
  color: white;
}

.test-btn.warning {
  background: #e6a23c;
  color: white;
}

.test-btn.info {
  background: #3498db;
  color: white;
}

.test-btn.confirm {
  background: #909399;
  color: white;
}

.chat-container {
  display: flex;
  flex-direction: column;
  height: 500px;
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  background: #f9f9f9;
}

.message {
  margin-bottom: 12px;
  padding: 12px 16px;
  border-radius: 8px;
  max-width: 80%;
  transition: all 0.3s ease;
  animation: messageSlideIn 0.3s ease;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  word-wrap: break-word;
}

.message:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
  transform: translateY(-2px);
}

.message.user {
  background: #d1e7dd;
  margin-left: auto;
  border-radius: 12px 12px 2px 12px;
}

.message.ai {
  background: #f8f9fa;
  margin-right: auto;
  border-radius: 12px 12px 12px 2px;
  color: #333;
  transition: all 0.1s ease-out;
}

.message.ai :deep(pre) {
  background: #1e1e1e;
  padding: 16px;
  border-radius: 8px;
  overflow-x: auto;
  margin: 10px 0;
  border: 1px solid #555;
  transition: all 0.3s ease;
  position: relative;
}

.message.ai :deep(pre:hover) {
  transform: scale(1.01);
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
}

@keyframes messageSlideIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes dotPulse {
  0% { opacity: 0; transform: translateY(0); }
  50% { opacity: 1; transform: translateY(-2px); }
  100% { opacity: 0; transform: translateY(0); }
}

.message.loading {
  background: transparent;
  color: #666;
  text-align: center;
}

.loading-text {
  display: inline-block;
}

.dots span {
  opacity: 0;
  animation: blink 1.4s infinite;
}

.dots span:nth-child(2) {
  animation-delay: 0.2s;
}

.dots span:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes blink {
  0%, 100% {
    opacity: 0;
  }
  50% {
    opacity: 1;
  }
}

.chat-input {
  display: flex;
  gap: 10px;
  padding: 15px;
  border-top: 1px solid #e1e8ed;
  background: white;
}

.chat-input textarea {
  flex: 1;
  padding: 10px;
  border: 1px solid #e1e8ed;
  border-radius: 8px;
  resize: none;
  transition: border-color 0.2s;
}

.chat-input textarea:focus {
  border-color: #007bff;
  outline: none;
  box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.1);
}

.chat-input button {
  padding: 10px 20px;
  border: none;
  border-radius: 8px;
  background: #007bff;
  color: white;
  cursor: pointer;
  transition: all 0.2s;
}

.chat-input button:hover {
  background: #0056b3;
  transform: translateY(-1px);
}

.chat-input button:disabled {
  background: #b3d7ff;
  cursor: not-allowed;
  transform: none;
}

.editor-preview-container {
  margin-top: 20px;
  background: #1e1e1e;
  border-radius: 8px;
  overflow: hidden;
}

.preview-header {
  padding: 12px 16px;
  background: #252526;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.preview-header h3 {
  color: #d4d4d4;
  font-size: 16px;
  margin: 0;
}

.content-length {
  color: #9cdcfe;
  font-size: 14px;
}

.preview-content {
  padding: 16px;
  color: #d4d4d4;
  font-family: 'Consolas', 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.5;
}

.preview-content pre {
  margin: 0;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.preview-content code {
  color: #d4d4d4;
}

.message.ai pre {
  background: #1e1e1e;
  padding: 12px;
  border-radius: 6px;
  margin: 8px 0;
  overflow-x: auto;
}

.message.ai code {
  font-family: 'Consolas', 'Courier New', monospace;
  color: #d4d4d4;
  font-size: 14px;
  line-height: 1.5;
}

.message.ai code .hljs-keyword {
  color: #569cd6;
}

.message.ai code .hljs-string {
  color: #ce9178;
}

.message.ai code .hljs-comment {
  color: #6a9955;
}

.message.ai code .hljs-title {
  color: #4ec9b0;
}

.message.ai code .hljs-number {
  color: #b5cea8;
}

.message.ai {
  max-width: 90%;
}

.message.ai pre::-webkit-scrollbar {
  height: 6px;
}

.message.ai pre::-webkit-scrollbar-track {
  background: #252526;
}

.message.ai pre::-webkit-scrollbar-thumb {
  background: #3e3e42;
  border-radius: 3px;
}

.message.ai :deep(pre code) {
  color: #ffffff !important;
  font-family: 'Fira Code', Consolas, Monaco, 'Andale Mono', monospace;
  font-size: 14px;
  line-height: 1.5;
}

.message.ai :deep(pre *) {
  color: #ffffff !important;
}

.message.ai {
  color: #333;
}

.message.ai :deep(p) {
  color: #333;
  margin: 0;
  line-height: 1.6;
}

.code-test-container {
  background: linear-gradient(to bottom, #ffffff, #f7f9fc);
  border-radius: 16px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
  padding: 24px;
  transition: all 0.3s ease;
}

.language-select {
  margin-bottom: 24px;
}

.language-dropdown {
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 12px;
  padding: 12px 16px;
  font-size: 15px;
  color: #1d1d1f;
  width: 100%;
  max-width: 300px;
  transition: all 0.2s ease;
}

.language-dropdown:hover {
  border-color: #0071e3;
  box-shadow: 0 0 0 3px rgba(0, 113, 227, 0.1);
}

.code-input-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.code-textarea {
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 12px;
  padding: 16px;
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 14px;
  line-height: 1.6;
  color: #1d1d1f;
  transition: all 0.2s ease;
  min-height: 200px;
  max-height: 600px;
  height: auto;
  resize: vertical;
  width: 100%;
}

.code-textarea:focus {
  border-color: #0071e3;
  box-shadow: 0 0 0 3px rgba(0, 113, 227, 0.1);
  outline: none;
}

.test-cases-section {
  background: rgba(255, 255, 255, 0.7);
  backdrop-filter: blur(10px);
  border-radius: 16px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  padding: 20px;
  margin-top: 24px;
  transition: all 0.3s ease;
}

.test-cases-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.test-cases-header h3 {
  margin: 0;
  font-size: 16px;
  color: #2d3748;
}

.test-cases-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
}

.switch {
  width: 51px;
  height: 31px;
}

.slider {
  background: rgba(0, 0, 0, 0.1);
  backdrop-filter: blur(5px);
}

.slider:before {
  width: 27px;
  height: 27px;
  left: 2px;
  bottom: 2px;
  background: white;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

input:checked + .slider {
  background: #0071e3;
}

input:checked + .slider:before {
  transform: translateX(20px);
}

.toggle-label {
  font-size: 14px;
  color: #4a5568;
}

.test-cases-container {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.test-case-item {
  background: rgba(255, 255, 255, 0.6);
  backdrop-filter: blur(10px);
  border-radius: 12px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  padding: 20px;
  transition: all 0.3s ease;
}

.test-case-item:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}

.test-case-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.test-case-header h4 {
  margin: 0;
  font-size: 14px;
  color: #4a5568;
}

.delete-btn {
  padding: 4px 8px;
  border: none;
  background: none;
  color: #e53e3e;
  cursor: pointer;
  border-radius: 4px;
  transition: all 0.2s;
}

.delete-btn:hover {
  background: #fed7d7;
}

.test-case-content {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.input-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.case-textarea {
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  padding: 12px;
  height: 100px;
  min-height: 60px;
  max-height: 200px;
  resize: vertical;
  width: 100%;
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 14px;
  line-height: 1.5;
  transition: all 0.2s ease;
}

.case-textarea:focus {
  border-color: #0071e3;
  box-shadow: 0 0 0 3px rgba(0, 113, 227, 0.1);
  outline: none;
}

.output-textarea {
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 12px;
  padding: 12px;
  transition: all 0.2s ease;
}

.submit-section {
  margin-top: 24px;
  display: flex;
  justify-content: flex-end;
  padding: 0 12px;
}

.test-result {
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(20px);
  border-radius: 16px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  overflow: hidden;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
  margin-top: 24px;
}

.result-header {
  background: rgba(247, 249, 252, 0.8);
  backdrop-filter: blur(10px);
  padding: 20px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}

.status-info {
  display: flex;
  align-items: center;
  gap: 8px;
}

.result-status {
  font-size: 16px;
  font-weight: 500;
}

.performance-info {
  display: flex;
  gap: 16px;
  color: #666;
  font-size: 0.9em;
}

.result-time, .result-memory {
  display: flex;
  align-items: center;
  gap: 4px;
}

.result-section {
  border-bottom: 1px solid #e2e8f0;
}

.result-section:last-child {
  border-bottom: none;
}

.section-header {
  padding: 12px 16px;
  background: #f8fafc;
  font-weight: 500;
  color: #2d3748;
  display: flex;
  align-items: center;
  gap: 8px;
}

.result-details {
  padding: 16px;
  background: #1a202c;
}

.result-details pre {
  margin: 0;
  white-space: pre-wrap;
  word-wrap: break-word;
  color: #e2e8f0;
  font-family: 'Fira Code', monospace;
  font-size: 14px;
  line-height: 1.5;
}

.result-section.error .section-header {
  background: #fff5f5;
  color: #c53030;
}

/* 状态样式 */
.test-result.success .result-status {
  color: #30d158;
}

.test-result.error .result-status {
  color: #ff453a;
}

.test-result.warning .result-status {
  color: #ff9f0a;
}

.test-cases-section {
  margin-top: 20px;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  padding: 16px;
}

.test-cases-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.test-cases-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
}

.switch {
  position: relative;
  display: inline-block;
  width: 50px;
  height: 24px;
}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #cbd5e0;
  transition: .4s;
  border-radius: 24px;
}

.slider:before {
  position: absolute;
  content: "";
  height: 16px;
  width: 16px;
  left: 4px;
  bottom: 4px;
  background-color: white;
  transition: .4s;
  border-radius: 50%;
}

input:checked + .slider {
  background-color: #3498db;
}

input:checked + .slider:before {
  transform: translateX(26px);
}

.toggle-label {
  font-size: 14px;
  color: #4a5568;
}

.test-cases-container {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.test-case-item {
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  padding: 16px;
  background: #f8fafc;
}

.test-case-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.test-case-header h4 {
  margin: 0;
  font-size: 14px;
  color: #4a5568;
}

.delete-btn {
  padding: 4px 8px;
  border: none;
  background: none;
  color: #e53e3e;
  cursor: pointer;
  border-radius: 4px;
  transition: all 0.2s;
}

.delete-btn:hover {
  background: #fed7d7;
}

.test-case-content {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.input-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.case-textarea {
  height: 100px;
  padding: 8px;
  border: 1px solid #e2e8f0;
  border-radius: 4px;
  resize: vertical;
  font-family: 'Fira Code', monospace;
  font-size: 14px;
  line-height: 1.5;
}

.test-btn.small {
  padding: 6px 12px;
  font-size: 12px;
}

.single-output-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.output-textarea {
  height: 120px;
  padding: 12px;
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  resize: vertical;
  font-family: 'Fira Code', monospace;
  font-size: 14px;
  line-height: 1.5;
}

.execution-limits-section {
  margin-top: 24px;
  background: rgba(255, 255, 255, 0.7);
  backdrop-filter: blur(10px);
  border-radius: 16px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  padding: 20px;
}

.limits-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.limits-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
}

.switch {
  position: relative;
  display: inline-block;
  width: 50px;
  height: 24px;
}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #cbd5e0;
  transition: .4s;
  border-radius: 24px;
}

.slider:before {
  position: absolute;
  content: "";
  height: 16px;
  width: 16px;
  left: 4px;
  bottom: 4px;
  background-color: white;
  transition: .4s;
  border-radius: 50%;
}

input:checked + .slider {
  background-color: #3498db;
}

input:checked + .slider:before {
  transform: translateX(26px);
}

.toggle-label {
  font-size: 14px;
  color: #4a5568;
}

.limits-content {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
  padding: 0;
  margin-top: 16px;
}

.limit-item {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.limit-input-container {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.limit-input-group {
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: 280px;
}

.limit-input {
  flex: 1;
  min-width: 80px;
  max-width: 120px;
  padding: 8px 12px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  font-size: 14px;
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(5px);
  transition: all 0.2s ease;
}

.unit-select {
  padding: 8px 12px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(5px);
  font-size: 14px;
  min-width: 80px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.input-error-message {
  font-size: 12px;
  color: #ff453a;
  margin-top: 2px;
}

.code-textarea:focus,
.case-textarea:focus,
.limit-input:focus,
.unit-select:focus {
  border-color: #0071e3;
  box-shadow: 0 0 0 3px rgba(0, 113, 227, 0.1);
  outline: none;
}

.code-textarea:hover,
.case-textarea:hover,
.limit-input:hover,
.unit-select:hover {
  border-color: rgba(0, 113, 227, 0.5);
}

/* 加载动画样式 */
.loading-container {
  display: flex;
  align-items: center;
  gap: 12px;
}

.loading-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.stage-indicator {
  display: flex;
  gap: 8px;
}

.stage-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.3);
  transition: all 0.3s ease;
}

.stage-dot.active {
  background: white;
  box-shadow: 0 0 12px rgba(255, 255, 255, 0.6);
  transform: scale(1.2);
}

.stage-dot.completed {
  background: white;
}

.stage-text {
  font-size: 12px;
  white-space: nowrap;
  min-width: 80px;
  text-align: center;
}

/* 添加动画效果 */
@keyframes pulse {
  0% { transform: scale(1); }
  50% { transform: scale(1.2); }
  100% { transform: scale(1); }
}

.stage-dot.active {
  animation: pulse 1s infinite;
}

/* 添加全屏加载蒙版 */
.loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
  backdrop-filter: blur(4px);
}

.loading-content {
  background: rgba(255, 255, 255, 0.1);
  padding: 30px;
  border-radius: 12px;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
}

/* 限制输入组样式 */
.limit-input-group {
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: 280px;
}

.unit-select {
  padding: 8px;
  border: 1px solid #e2e8f0;
  border-radius: 4px;
  background: white;
  font-size: 14px;
}

.unit-label {
  color: #4a5568;
  font-size: 14px;
  min-width: 30px;
}

/* 超限状态样式 */
.test-result.limit-exceeded .result-header {
  background: #fff5f5;
}

.performance-info .exceeded {
  color: #e53e3e;
  font-weight: 600;
}

/* 加载动画增强 */
.stage-dot {
  width: 10px;
  height: 10px;
  background: rgba(255, 255, 255, 0.2);
  box-shadow: 0 0 10px rgba(255, 255, 255, 0.1);
}

.stage-dot.active {
  background: #3498db;
  box-shadow: 0 0 20px rgba(52, 152, 219, 0.6);
}

.stage-dot.completed {
  background: #2ecc71;
  box-shadow: 0 0 15px rgba(46, 204, 113, 0.4);
}

.stage-text {
  color: white;
  font-size: 16px;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

/* 添加平滑滚动 */
.code-test-container {
  scroll-behavior: smooth;
}

/* 添加响应式hover效果 */
@media (hover: hover) {
  .test-btn:hover {
    transform: translateY(-2px);
  }
  
  .language-dropdown:hover {
    border-color: #0071e3;
  }
  
  .code-textarea:hover,
  .case-textarea:hover,
  .output-textarea:hover {
    border-color: rgba(0, 113, 227, 0.5);
  }
}

/* 添加深色模式支持 */
@media (prefers-color-scheme: dark) {
  .code-test-container {
    background: linear-gradient(to bottom, #1d1d1f, #2d2d2f);
  }
  
  .language-dropdown,
  .code-textarea,
  .case-textarea,
  .output-textarea {
    background: rgba(255, 255, 255, 0.1);
    color: #f5f5f7;
  }
  
  .test-cases-section,
  .execution-limits-section,
  .test-case-item {
    background: rgba(255, 255, 255, 0.05);
  }

  .limit-input,
  .unit-select {
    background: rgba(255, 255, 255, 0.1);
    color: #f5f5f7;
    border-color: rgba(255, 255, 255, 0.1);
  }

  .limit-input:hover,
  .unit-select:hover {
    border-color: rgba(0, 113, 227, 0.5);
  }

  .execution-limits-section {
    background: rgba(255, 255, 255, 0.05);
  }
}
</style> 